package com.cskaoyan.javase.oop1._16access._3why;

/**
 * 访问权限修饰符的作用/为什么使用访问权限修饰符?
 *
 * 那么就像给门加锁，是警告你不能逾越界限，否则就是违法操作一样。
 * 访问权限的使用，最基本的，自然是用来控制访问权限的（这是废话）。
 * 但也隐含了警告和暗示的作用：
 * 告诉代码的使用者，哪些地方不要触碰，哪些地方应该使用。
 * 起到警告、约束和指导代码使用者的功能。
 * 比如:
 *      1.专门提供给外界使用的，推荐使用的，用public。
 *          告诉别人：这里是你需要关注、了解和使用的地方。
 *          所有明确提供给外界使用，实现功能的方法，需要用public修饰。
 *      2.但是那些明确不需要外界触碰,不需要外界了解的(实际上了解的也没用的),就应该使用private修饰
 *          告诉别人: 这里不需要你关注,你无需关注,只需要关注那些有访问权限的地方即可.
 * 实际案例：
 *      1.中间方法私有化。
 *          比如一个类的对象需要对外提供功能服务,这样一个方法就应该是public修饰的
 *          而实现这个对外public方法的一些中间的过程方法,步骤方法,不需要提供给外界使用,那就应该私有化它.
 *          称之为"中间方法私有化"
 *
 *      2.工具类。当中的方法全部都是static修饰的静态方法，使用工具类时，只需要类名.调用方法即可
 *          不需要使用工具类的对象
 *          所以工具类干脆禁止创建对象，私有化构造器
 *          这是告诉使用者，不要尝试创建对象来使用工具类。
 *
 *      3.工厂的设计模式，还有单例的设计模式。
 *          都需要私有化构造器，阻止在外界正常new对象。
 *          工厂设计模式往往需要借助反射在一个工厂类中生产对象。
 *          单例私有化构造器之后，需要在自身类中提供一个方法来提供单例对象。
 *
 * 以上案例，我们使用访问权限修饰符，好处是什么？
 * 如果你能够严格按照上述描述使用访问权限修饰符，
 *      那么好处是显而易见的，把代码的开发者和代码的使用者给区分开来了：
 *      1.代码使用者无需关心没有访问权限的代码，仅需要关心具有访问权限的部分就可以了。
 *          私有或者没有访问权限的部分，既然不让我看，不让我用，那我就老老实实不看，不用。
 *          实际上，当你去使用别人的代码时，你也不希望需要完全读懂所有代码，才能够使用吧？
 *      2.代码开发者，可以自由的开发，对外界没有访问权限部分的代码。
 *      这些私有的，或者对外界不可见部分的代码，叫做隐藏代码的具体实现细节，可以很方便的修改代码实现。
 *      想一想，如果一个方法是public修饰的，在外界多处被使用，你敢随便就动这个方法代码吗？
 *
 * 所以，我们就可以总结出，我们在实际开发中，使用类中结构的访问权限修饰符的原则：
 *      1.尽量私有化，方便自己修改代码，隐藏实现细节。
 *      2.如果不能私有化，那也应该尽量少的给予访问权限，先从默认权限开始考虑。
 *      3.只有确定这个结构，一定需要在外部（尤其是不同包下）被访问时，才考虑给public，尽量少给public。
 * 权限这个东西，要吝啬，不要"大方"！
 *
 * @since 11:48
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        Student s = new Student(18, "张三");
        s.printStudent();
        // s.test

        method();
    }

    // Access can be private 因为这个方法仅在类的内部被调用，所以推荐私有化它。
    // 也就是说IDEA认为这个方法是一个中间方法
    public static void method() {

    }
}

class Student {
    int age;
    String name;

    public Student(int age, String name) {
        this.age = age;
        this.name = name;
    }

    // 对外提供打印自身类对象属性的功能
    // Access can be package-private
    /*
        public的方法对外权限很大
        一旦修改会对外界使用造成直接影响
        所以public方法的修改往往需要慎重考虑

        在公司当中，一旦一个方法是public 个人建议宁愿再重新写一个功能95%都一样的方法
        也不要直接修改
        除非你真的确信改了没问题
     */
    public void printStudent() {
        test();
        System.out.println("age = " + age + ", name = " + name);
    }

    // test方法本身不对外直接提供服务,应该私有化
    /*
        这个私有方法对外不可见，这个方法的修改
        最多只能影响该类本身
        对外界没有直接影响
        所以对它做出修改，程序员是很放心的
     */
    private void test() {
        System.out.println("实现对外打印学生对象功能的一些中间操作!");
    }
}